package com.wanger.service.impl;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.github.yulichang.base.MPJBaseServiceImpl;
import com.github.yulichang.wrapper.MPJLambdaWrapper;
import com.wanger.mapper.SysUserMapper;
import com.wanger.model.connect.SysAuthorityResource;
import com.wanger.model.connect.SysRoleAuthority;
import com.wanger.model.connect.SysUserRole;
import com.wanger.model.entity.*;
import com.wanger.service.*;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.List;

/**
 * @Author: wanger
 * @Date: 2023/8/17 22:15
 * @Description:
 */

@Service
public class SysUserServiceImpl extends MPJBaseServiceImpl<SysUserMapper, SysUser> implements SysUserService {

    @Resource
    private SysUserRoleServiceImpl sysUserRoleService;

    @Resource
    private SysUserDetailService sysUserDetailService;

    @Resource
    private SysRoleService sysRoleService;

    @Resource
    private SysRoleAuthorityService sysRoleAuthorityService;

    @Resource
    private SysAuthorityService sysAuthorityService;

    @Resource
    private SysAuthorityResourceService sysAuthorityResourceService;

    @Resource
    private SysResourceService sysResourceService;

    @Override
    public IPage<SysResource> deepPageTurning(Integer pageNum, Integer pageSize, String name, String url) {
        MPJLambdaWrapper<SysResource> wrapper = new MPJLambdaWrapper<>();
        if (StrUtil.isNotBlank(name)) wrapper.like(SysResource::getName, name);
        if (StrUtil.isNotBlank(url)) wrapper.like(SysResource::getUrl, url);
        return sysResourceService.page(new Page<>(pageNum, pageSize), wrapper);
    }

    @Override
    @Transactional
    public boolean addData(List<SysUser> userList) {
        if (CollUtil.isNotEmpty(userList)) {
            if (this.saveBatch(userList)) {
                List<SysRole> roleList = new ArrayList<>();
                List<SysAuthority> authorityList = new ArrayList<>();
                List<SysResource> resourceList = new ArrayList<>();
                userList.forEach(u -> {
                    List<SysRole> roleInfo = u.getRoleInfo();
                    if (CollUtil.isNotEmpty(roleInfo)) {
                        roleList.addAll(roleInfo);
                        roleInfo.forEach(r -> {
                            List<SysAuthority> authorityInfo = r.getAuthorityInfo();
                            if (CollUtil.isNotEmpty(authorityInfo)) {
                                authorityList.addAll(authorityInfo);
                                authorityInfo.forEach(a -> {
                                    List<SysResource> resourceInfo = a.getResourceInfo();
                                    if (CollUtil.isNotEmpty(resourceInfo)) {
                                        resourceList.addAll(resourceInfo);
                                    }
                                });
                            }
                        });
                    }
                });
                if (CollUtil.isNotEmpty(roleList)) sysRoleService.saveBatch(roleList);
                if (CollUtil.isNotEmpty(authorityList)) sysAuthorityService.saveBatch(authorityList);
                if (CollUtil.isNotEmpty(resourceList)) sysResourceService.saveBatch(resourceList);
                List<SysUserRole> userRoles = new ArrayList<>();
                List<SysRoleAuthority> roleAuthority = new ArrayList<>();
                List<SysAuthorityResource> authorityResource = new ArrayList<>();
                List<SysUserDetail> sysUserDetails = new ArrayList<>();
                userList.forEach(u -> {
                    List<SysRole> roleInfo = u.getRoleInfo();
                    if (u.getSysUserDetail() != null) sysUserDetails.add(u.getSysUserDetail());
                    if (CollUtil.isNotEmpty(roleInfo)) {
                        roleInfo.forEach(r -> {
                            userRoles.add(new SysUserRole(u.getId(), r.getId()));
                            List<SysAuthority> authorityInfo = r.getAuthorityInfo();
                            if (CollUtil.isNotEmpty(authorityInfo)) {
                                authorityInfo.forEach(a -> {
                                    roleAuthority.add(new SysRoleAuthority(r.getId(), a.getId()));
                                    List<SysResource> resourceInfo = a.getResourceInfo();
                                    if (CollUtil.isNotEmpty(resourceInfo)) {
                                        resourceInfo.forEach(re -> authorityResource.add(new SysAuthorityResource(a.getId(), re.getId())));
                                    }
                                });
                            }
                        });
                    }
                });
                if (CollUtil.isNotEmpty(sysUserDetails)) sysUserDetailService.saveBatch(sysUserDetails);
                if (CollUtil.isNotEmpty(userRoles)) sysUserRoleService.saveBatch(userRoles);
                if (CollUtil.isNotEmpty(roleAuthority)) sysRoleAuthorityService.saveBatch(roleAuthority);
                if (CollUtil.isNotEmpty(authorityResource)) sysAuthorityResourceService.saveBatch(authorityResource);
                return true;
            }
        }
        return false;
    }

    @Override
    public SysUser queryDetailsV1(String id) {
        if (StrUtil.isBlank(id)) return new SysUser();
        return this.selectJoinOne(
                SysUser.class,
                new MPJLambdaWrapper<SysUser>()
                        .selectAll(SysUser.class)
                        .selectAssociation(SysUserDetail.class, SysUser::getSysUserDetail)
                        .leftJoin(SysUserDetail.class, SysUserDetail::getUserId, SysUser::getId)
                        .eq(SysUser::getId, id)
        );
    }

    @Override
    public SysUser queryDetailsV2(String id) {
        if (StrUtil.isBlank(id)) return new SysUser();
        else return this.selectJoinOne(
                SysUser.class,
                new MPJLambdaWrapper<SysUser>()
                        .selectAll(SysUser.class)
                        .selectCollection(
                                SysRole.class,
                                SysUser::getRoleInfo,
                                r -> r.collection(
                                        SysAuthority.class,
                                        SysRole::getAuthorityInfo,
                                        a -> a.collection(
                                                SysResource.class, SysAuthority::getResourceInfo
                                        )
                                )
                        )
                        .leftJoin(SysUserRole.class, SysUserRole::getUserId, SysUser::getId)
                        .leftJoin(SysRole.class, SysRole::getId, SysUserRole::getRoleId)
                        .leftJoin(SysRoleAuthority.class, SysRoleAuthority::getRoleId, SysRole::getId)
                        .leftJoin(SysAuthority.class, SysAuthority::getId, SysRoleAuthority::getAuthorityId)
                        .leftJoin(SysAuthorityResource.class, SysAuthorityResource::getAuthorityId, SysAuthority::getId)
                        .leftJoin(SysResource.class, SysResource::getId, SysAuthorityResource::getResourceId)
                        .eq(SysUser::getId, id)
        );
    }

    @Override
    public IPage<SysUser> queryDetailsV3(Integer pageNum, Integer pageSize, String userName) {
        MPJLambdaWrapper<SysUser> wrapper = new MPJLambdaWrapper<>(SysUser.class)
                .selectAll(SysUser.class)
                .selectCollection(
                        SysRole.class,
                        SysUser::getRoleInfo,
                        r -> r.collection(
                                SysAuthority.class,
                                SysRole::getAuthorityInfo,
                                a -> a.collection(
                                        SysResource.class, SysAuthority::getResourceInfo
                                )
                        )
                )
                .leftJoin(SysUserRole.class, SysUserRole::getUserId, SysUser::getId)
                .leftJoin(SysRole.class, SysRole::getId, SysUserRole::getRoleId)
                .leftJoin(SysRoleAuthority.class, SysRoleAuthority::getRoleId, SysRole::getId)
                .leftJoin(SysAuthority.class, SysAuthority::getId, SysRoleAuthority::getAuthorityId)
                .leftJoin(SysAuthorityResource.class, SysAuthorityResource::getAuthorityId, SysAuthority::getId)
                .leftJoin(SysResource.class, SysResource::getId, SysAuthorityResource::getResourceId);
        if (StrUtil.isNotBlank(userName)) wrapper.eq(SysUser::getName, userName);
        return super.baseMapper.selectJoinPage(new Page<>(pageNum, pageSize, true), SysUser.class, wrapper);
    }


    @Override
    public List<SysUser> queryDetailsV3_1(List<String> userIds) {
        if (CollUtil.isEmpty(userIds)) return null;
        else return this.selectJoinList(SysUser.class, new MPJLambdaWrapper<>(SysUser.class)
                .selectAll(SysUser.class)
                .selectCollection(
                        SysRole.class,
                        SysUser::getRoleInfo,
                        r -> r.collection(
                                SysAuthority.class,
                                SysRole::getAuthorityInfo,
                                a -> a.collection(
                                        SysResource.class, SysAuthority::getResourceInfo
                                )
                        )
                )
                .leftJoin(SysUserRole.class, SysUserRole::getUserId, SysUser::getId)
                .leftJoin(SysRole.class, SysRole::getId, SysUserRole::getRoleId)
                .leftJoin(SysRoleAuthority.class, SysRoleAuthority::getRoleId, SysRole::getId)
                .leftJoin(SysAuthority.class, SysAuthority::getId, SysRoleAuthority::getAuthorityId)
                .leftJoin(SysAuthorityResource.class, SysAuthorityResource::getAuthorityId, SysAuthority::getId)
                .leftJoin(SysResource.class, SysResource::getId, SysAuthorityResource::getResourceId)
                .in(SysUser::getId, userIds));
    }

    @Override
    public SysUser queryDetailsV4(String id) {
        if (StrUtil.isBlank(id)) return new SysUser();
        else return this.selectJoinOne(
                SysUser.class,
                new MPJLambdaWrapper<SysUser>()
                        .selectAll(SysUser.class)
                        .selectAssociation(SysUserDetail.class, SysUser::getSysUserDetail)
                        .leftJoin(SysUserDetail.class, SysUserDetail::getUserId, SysUser::getId)
                        .selectCollection(
                                SysRole.class,
                                SysUser::getRoleInfo,
                                r -> r.collection(
                                        SysAuthority.class,
                                        SysRole::getAuthorityInfo,
                                        a -> a.collection(
                                                SysResource.class, SysAuthority::getResourceInfo
                                        )
                                )
                        )
                        .leftJoin(SysUserRole.class, SysUserRole::getUserId, SysUser::getId)
                        .leftJoin(SysRole.class, SysRole::getId, SysUserRole::getRoleId)
                        .leftJoin(SysRoleAuthority.class, SysRoleAuthority::getRoleId, SysRole::getId)
                        .leftJoin(SysAuthority.class, SysAuthority::getId, SysRoleAuthority::getAuthorityId)
                        .leftJoin(SysAuthorityResource.class, SysAuthorityResource::getAuthorityId, SysAuthority::getId)
                        .leftJoin(SysResource.class, SysResource::getId, SysAuthorityResource::getResourceId)
                        .eq(SysUser::getId, id)
        );
    }

    @Override
    public IPage<SysUser> queryDetailsV5(Integer pageNum, Integer pageSize, String userName) {
        MPJLambdaWrapper<SysUser> wrapper = new MPJLambdaWrapper<>(SysUser.class)
                .selectAll(SysUser.class)
                .selectAssociation(SysUserDetail.class, SysUser::getSysUserDetail)
                .leftJoin(SysUserDetail.class, SysUserDetail::getUserId, SysUser::getId)
                .selectCollection(
                        SysRole.class,
                        SysUser::getRoleInfo,
                        r -> r.collection(
                                SysAuthority.class,
                                SysRole::getAuthorityInfo,
                                a -> a.collection(
                                        SysResource.class, SysAuthority::getResourceInfo
                                )
                        )
                )
                .leftJoin(SysUserRole.class, SysUserRole::getUserId, SysUser::getId)
                .leftJoin(SysRole.class, SysRole::getId, SysUserRole::getRoleId)
                .leftJoin(SysRoleAuthority.class, SysRoleAuthority::getRoleId, SysRole::getId)
                .leftJoin(SysAuthority.class, SysAuthority::getId, SysRoleAuthority::getAuthorityId)
                .leftJoin(SysAuthorityResource.class, SysAuthorityResource::getAuthorityId, SysAuthority::getId)
                .leftJoin(SysResource.class, SysResource::getId, SysAuthorityResource::getResourceId);
        if (StrUtil.isNotBlank(userName)) wrapper.eq(SysUser::getName, userName);
        return this.selectJoinListPage(new Page<>(pageNum, pageSize, true), SysUser.class, wrapper);
    }
}
